Skip to content

⚡ Bolt: [performance improvement] Optimize stats computation to single O(n) pass#268

Open
KxlSys wants to merge 1 commit into
mainfrom
bolt-stats-optimization-11162564375199497311
Open

⚡ Bolt: [performance improvement] Optimize stats computation to single O(n) pass#268
KxlSys wants to merge 1 commit into
mainfrom
bolt-stats-optimization-11162564375199497311

Conversation

@KxlSys

@KxlSys KxlSys commented Jul 9, 2026

Copy link
Copy Markdown
Owner

💡 What: Refactored the computeStats logic in both src/pages/about-page.tsx and src/hooks/use-platform-stats.ts to perform data aggregation in a single O(n) pass instead of chaining multiple array methods.
🎯 Why: When rendering the About page or loading platform stats, the codebase was previously doing 8-10 consecutive iterations over the entire profiles array using .map().filter(), .flatMap(), etc. This blocked the main thread and caused excessive intermediate array memory allocations.
📊 Impact: Reduces time complexity from ~8 * O(n) to 1 * O(n) for profile parsing. Eliminates intermediate array allocations, reducing memory usage and garbage collection pauses on lower-end devices.
🔬 Measurement: Verify by running pnpm test (all pass) and manually profiling the execution time of the computeStats function in Chrome DevTools when loading the /a-propos route with thousands of mock profiles; execution time should be significantly shorter without long GC tasks.


PR created automatically by Jules for task 11162564375199497311 started by @KxlSys

Summary by CodeRabbit

  • Refactor

    • Improved how platform and About page statistics are calculated behind the scenes, while keeping the displayed results the same.
    • Optimized aggregation for large datasets by reducing repeated passes over the same data.
    • Updated the About page’s stats and growth metrics to use consolidated counting for more efficient processing.
  • Documentation

    • Added a note about best practices for efficient data aggregation.

- Consolidated multiple `.map().filter()` and `.flatMap()` calls in `src/hooks/use-platform-stats.ts` into a single loop.
- Consolidated ~8 redundant iterations over the `profiles` array in `src/pages/about-page.tsx` into a single `for` loop.
- Replaced secondary iterations over the arrays to calculate totals with size lookups on the generated sets/dictionaries.
- Added a Bolt learning journal entry in `.jules/bolt.md`.

Co-authored-by: KxlSys <116387953+KxlSys@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@vercel

vercel Bot commented Jul 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
bisomaptech Ready Ready Preview, Comment Jul 9, 2026 3:18pm

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: aa744f51-45f3-4510-b01d-4739274af45e

📥 Commits

Reviewing files that changed from the base of the PR and between 7dc0352 and bb22737.

📒 Files selected for processing (3)
  • .jules/bolt.md
  • src/hooks/use-platform-stats.ts
  • src/pages/about-page.tsx

📝 Walkthrough

Walkthrough

This PR refactors two computeStats functions—in use-platform-stats.ts and about-page.tsx—to replace multiple array-pass operations (map/filter/flatMap) with single-loop accumulation using counters and Sets/maps. A documentation note describing this optimization pattern is added to .jules/bolt.md.

Changes

Single-pass stats aggregation

Layer / File(s) Summary
Platform stats hook refactor
src/hooks/use-platform-stats.ts
computeStats now uses a single for...of loop with a collaboration counter and two Sets for unique cities and tech entries, replacing prior map/filter/flatMap passes while preserving returned fields.
About page stats refactor
src/pages/about-page.tsx
computeStats consolidates role, experience, tech, city, monthly growth, collaboration, and active-last-week counting into one loop over profiles; rendering arrays and totalCities/allTechs now derive from the resulting count maps instead of separate passes.
Aggregation pattern documentation
.jules/bolt.md
Adds a note describing consolidating repeated array iterations into a single loop with multiple accumulators.

Estimated code review effort: 2 (Simple) | ~15 minutes

Possibly related PRs

  • KxlSys/BisoMapTech#52: Both PRs refactor computeStats in src/pages/about-page.tsx to reduce the number of aggregation passes over profile data.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: optimizing stats computation to a single O(n) pass for performance.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bolt-stats-optimization-11162564375199497311

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

Excellente initiative de Pull Request ! Cette PR s'attaque à un problème de performance courant et démontre une bonne compréhension des optimisations en JavaScript, en particulier dans un contexte d'application web dynamique comme BisoMapTech. Le fichier .jules/bolt.md est une excellente pratique pour documenter les apprentissages et les décisions d'optimisation.

Voici la revue détaillée :


Analyse Détaillée de la Pull Request

1. Failles de sécurité

Aucune faille de sécurité majeure n'est introduite ou exposée par cette Pull Request. Les modifications concernent uniquement la logique de traitement et d'agrégation de données existantes, sans interagir avec des entrées utilisateur non validées ou des systèmes sensibles (authentification, base de données directe).

  • Absence d'injections / XSS : Le code ne manipule pas de chaînes de caractères provenant de l'utilisateur pour les insérer directement dans le DOM ou dans des requêtes sensibles. Les données traitées (profiles, city, tech_stack, etc.) sont utilisées pour des calculs statistiques internes.
  • Exposition de données sensibles : Aucune nouvelle donnée sensible n'est exposée. Les statistiques calculées sont agrégées et anonymisées de facto.
  • Secrets exposés : Aucun secret n'est exposé.

🟢 Faible - Aucun problème de sécurité détecté. C'est une refonte interne qui n'impacte pas la surface d'attaque.


2. Bugs potentiels

Les changements apportés semblent robustes et gèrent correctement les cas limites.

  • Gestion des tableaux vides : La vérification if (total === 0) au début des deux fonctions computeStats est maintenue et garantit que le code ne tente pas de traiter des tableaux vides, évitant ainsi des erreurs de division par zéro ou des accès à des indices inexistants.
  • Gestion des valeurs null/undefined :
    • Dans use-platform-stats.ts, l'utilisation de if (p.city) et if (p.tech_stack) (avant la boucle sur les techs) gère correctement les propriétés qui pourraient être null ou undefined, similaire à l'opérateur ?? [] de l'ancienne version.
    • Dans about-page.tsx, des vérifications similaires (if (p.tech_stack), if (p.city)) sont en place et fonctionnent comme prévu.
    • Pour p.last_seen_at, la vérification if (p.last_seen_at && new Date(p.last_seen_at) >= weekAgo) est également correcte.
  • Logique de calcul équivalente : La logique de chaque agrégation (nombre total d'utilisateurs, villes, taux de collaboration, technologies, rôles, expérience, etc.) a été fidèlement traduite dans la nouvelle approche en un seul passage.
    • Le remplacement de new Set(profiles.map((p) => p.city).filter(Boolean)).size par citiesSet.size ou Object.keys(cityCounts).length est correct et plus performant.
    • Le calcul des dates (now, weekAgo) en dehors de la boucle est une bonne pratique.
  • Conversion des dates : new Date(p.created_at) et new Date(p.last_seen_at) supposent que created_at et last_seen_at sont des chaînes de caractères au format ISO ou tout autre format parsable par le constructeur Date. C'est une hypothèse standard, mais il est bon de le noter.

🟢 Faible - Aucun bug potentiel significatif détecté. Les cas limites semblent bien gérés.


3. Qualité du code

La qualité du code est globalement améliorée en termes de performance et de respect des bonnes pratiques d'optimisation, même si cela introduit une légère augmentation de la complexité cyclomatique dans le bloc for.

  • Lisibilité et maintenabilité :
    • Amélioration de la performance : L'objectif principal est atteint avec brio. La consolidation de multiples itérations en un seul passage O(n) est une optimisation significative, surtout pour des jeux de données plus importants, et réduit la pression sur le garbage collector en évitant la création d'arrays intermédiaires. C'est une excellente pratique de performance.
    • Lisibilité du about-page.tsx computeStats : La nouvelle boucle unique est très dense. Elle gère un grand nombre d'agrégations différentes. Bien que performante, cela peut rendre le code un peu plus difficile à lire et à maintenir si de nombreuses nouvelles métriques devaient être ajoutées ou si une métrique spécifique devait être déboguée. Les commentaires // Roles, // Experience, etc., sont essentiels ici et sont bien placés.
    • Documentation (.jules/bolt.md) : L'ajout de la section "Avoid Multiple Array Iterations for Data Aggregation" dans bolt.md est exemplaire. Il documente le pourquoi de cette optimisation, ce qui est crucial pour la base de connaissances du projet et la compréhension future par l'équipe.
    • Cohérence des annotations : L'utilisation des commentaires // ⚡ Bolt: ... est cohérente avec la documentation et met en évidence la nature des changements.
  • Respect du typage strict TypeScript :
    • Le typage strict est respecté. L'utilisation de Set<string>() est correcte et précise. Les Record<string, number> sont également bien utilisés.
    • Les types des paramètres des fonctions n'ont pas changé, ce qui maintient l'intégrité de l'interface.
  • Bonnes pratiques :
    • Optimisation proactive : Cette PR est un excellent exemple d'optimisation proactive basée sur un "apprentissage" documenté.
    • Dérivation des totaux : L'optimisation Object.keys(cityCounts).length au lieu d'une nouvelle itération pour totalCities ou allTechs est une autre petite mais significative amélioration, montrant une pensée rigoureuse sur la performance.

🟠 Haute (pour l'amélioration de la qualité) - L'amélioration des performances est significative. La densité de la boucle unique dans about-page.tsx est un petit compromis de lisibilité, mais justifié par le gain de performance et compensé par de bons commentaires.


Suggestions concrètes de code de correction

Globalement, le code est très bon. Les suggestions ci-dessous sont mineures et visent à peaufiner la lisibilité ou à renforcer la robustesse dans des cas très spécifiques.

1. Clarification du typage pour citiesSet et techsSet (use-platform-stats.ts)

Bien que TypeScript puisse inférer le type correctement après la première insertion, le rendre explicite dès la déclaration peut améliorer la lisibilité pour les nouveaux venus sur le code. C'est déjà fait, mais c'est une bonne pratique.
(Aucune correction nécessaire, juste une confirmation que c'est bien fait).

// src/hooks/use-platform-stats.ts
// ...
  let collab = 0;
  const citiesSet = new Set<string>(); // Déjà explicite, très bien !
  const techsSet = new Set<string>();   // Déjà explicite, très bien !
// ...

2. Utilisation de constantes pour les strings littérales des rôles/expériences (about-page.tsx)

Dans about-page.tsx, les chaînes de caractères comme "Junior", "Intermédiaire", "Senior", "Expert" sont utilisées plusieurs fois. Pour la maintenabilité, si ces libellés devaient changer, il serait préférable d'utiliser des constantes. C'est un point de détail, mais cela améliore la robustesse.

// src/pages/about-page.tsx
// ...
  // Define constants for experience levels
  const EXPERIENCE_JUNIOR = "Junior";
  const EXPERIENCE_INTERMEDIATE = "Intermédiaire";
  const EXPERIENCE_SENIOR = "Senior";
  const EXPERIENCE_EXPERT = "Expert";

  const expCounts: Record<string, number> = {};
  // ... (inside the loop)
    // Experience
    expCounts[p.experience_level] = (expCounts[p.experience_level] || 0) + 1;
  // ...
  const experience = [
    {
      label: EXPERIENCE_JUNIOR, // Utiliser la constante
      value: expCounts[EXPERIENCE_JUNIOR] || 0,
      pct: Math.round(((expCounts[EXPERIENCE_JUNIOR] || 0) / total) * 100),
    },
    {
      label: EXPERIENCE_INTERMEDIATE, // Utiliser la constante
      value: expCounts[EXPERIENCE_INTERMEDIATE] || 0,
      pct: Math.round(((expCounts[EXPERIENCE_INTERMEDIATE] || 0) / total) * 100),
    },
    {
      label: EXPERIENCE_SENIOR, // Utiliser la constante
      value: expCounts[EXPERIENCE_SENIOR] || 0,
      pct: Math.round(((expCounts[EXPERIENCE_SENIOR] || 0) / total) * 100),
    },
    {
      label: EXPERIENCE_EXPERT, // Utiliser la constante
      value: expCounts[EXPERIENCE_EXPERT] || 0,
      pct: Math.round(((expCounts[EXPERIENCE_EXPERT] || 0) / total) * 100),
    },
  ];
// ...

Sévérité : 🟢 Faible (Amélioration de la maintenabilité, pas un bug)


Résumé Général

Cette Pull Request est une excellente contribution à BisoMapTech. Elle résout un problème de performance identifié de manière élégante et efficace, tout en respectant les bonnes pratiques de développement (typage TypeScript, gestion des cas limites). L'ajout à bolt.md est particulièrement appréciable et renforce la culture d'apprentissage et d'optimisation de l'équipe.

L'impact sur la sécurité est nul, et les risques de bugs sont très faibles grâce à une transposition fidèle de la logique et une bonne gestion des valeurs null/undefined et des tableaux vides. La qualité du code est globalement améliorée par l'optimisation, bien que la densité du code dans la boucle de about-page.tsx demande une attention un peu plus soutenue à la lecture.

Verdict : Cette PR est prête à être fusionnée après examen de la suggestion mineure sur les constantes. Très bon travail !

@KxlSys
KxlSys enabled auto-merge (rebase) July 10, 2026 16:26
@KxlSys
KxlSys disabled auto-merge July 10, 2026 16:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant